package gatperdut.chato.core.interpreter.actions;

import gatperdut.chato.constants.CSConstantsCommandResult.CommandExecutionResult;
import gatperdut.chato.core.characters.BaseController;
import gatperdut.chato.core.interpreter.actions.generic.ManipulationAction;
import gatperdut.chato.core.interpreter.grammar.comminfo.ManipulationDoorInfo;
import gatperdut.chato.core.item.ItemController;
import gatperdut.chato.core.room.DoorController;
import gatperdut.chato.core.room.RoomController;

public class ManipulationDoorAction extends ManipulationAction {

    public ManipulationDoorAction( ManipulationDoorInfo info, BaseController entityController ) {
        super( info, entityController );
    }

    @Override
    public CommandExecutionResult perform() {
        checkForRunningCraft();

        String emote = getLastPartEmote();
        if ( emote == null ) {
            getEntityController().tx( "Check your emote." );
            return CommandExecutionResult.OK;
        }

        RoomController rc = getEntityController().getRoomController();
        DoorController dc = rc.getExitsController().getAdjacentDoorController( getInfo().getDirection() );
        if ( dc == null ) {
            getEntityController().tx( "There's no door in that direction." );
            return CommandExecutionResult.OK;
        }

        switch ( getInfo().getManipulationType() ) {
        case CLOSE:
            if ( !dc.getDoor().isOpen() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " is already closed." );
                return CommandExecutionResult.OK;
            }

            dc.getDoor().setOpen( false );

            getEntityController().getEchoes().txCloseDoor( dc, getInfo().getDirection(), emote );

            return CommandExecutionResult.OK;
        case OPEN:
            if ( dc.getDoor().isOpen() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " is already open." );
                return CommandExecutionResult.OK;
            }
            if ( dc.isLockable() && dc.getLockController().isLocked() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " seems to be locked." );
                return CommandExecutionResult.OK;
            }

            dc.getDoor().setOpen( true );

            getEntityController().getEchoes().txOpenDoor( dc, getInfo().getDirection(), emote );

            return CommandExecutionResult.OK;
        case LOCK:
            if ( dc.getLockController() == null ) {
                getEntityController().tx( "There's no apparent way to lock " + dc.getDoor().getDesc() + "." );
                return CommandExecutionResult.OK;
            }
            if ( dc.getDoor().isOpen() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " needs to be closed first." );
                return CommandExecutionResult.OK;
            }
            if ( dc.isLockable() && dc.getLockController().isLocked() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " is already locked." );
                return CommandExecutionResult.OK;
            }

            {
                ItemController possibleKey = getEntityController().getInventoryController().findKeyForDoor( dc );
                if ( possibleKey != null ) {
                    dc.getLockController().setLocked( true );
                    getEntityController().getEchoes().txLockDoor( dc, getInfo().getDirection(), possibleKey, emote );
                    return CommandExecutionResult.OK;
                }
            }

            getEntityController().tx( "You don't seem to be carrying anything to lock " + dc.getDoor().getDesc() + " with." );
            return CommandExecutionResult.OK;

        case UNLOCK:
            if ( dc.getLockController() == null ) {
                getEntityController().tx( "There's no apparent way to unlock " + dc.getDoor().getDesc() + "." );
                return CommandExecutionResult.OK;
            }
            if ( dc.getDoor().isOpen() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " is already open!" );
                return CommandExecutionResult.OK;
            }
            if ( dc.isLockable() && !dc.getLockController().isLocked() ) {
                getEntityController().tx( dc.getDoor().getDesc() + " is not locked." );
                return CommandExecutionResult.OK;
            }

            {
                ItemController possibleKey = dc.getLockController().unlocksWith( getEntityController().getInventoryController() );
                if ( possibleKey != null ) {
                    dc.getLockController().setLocked( false );
                    getEntityController().getEchoes().txUnlockDoor( dc, getInfo().getDirection(), possibleKey, emote );
                    return CommandExecutionResult.OK;
                }
            }

            getEntityController().tx( "You don't seem to be carrying anything to unlock " + dc.getDoor().getDesc() + " with." );
            return CommandExecutionResult.OK;

        default:
            throw new IllegalArgumentException( "Door manipulation action with unknown manipulation type." );
        }

    }

    @Override
    public ManipulationDoorInfo getInfo() {
        return (ManipulationDoorInfo) super.getInfo();
    }

}
